package service

import (
	"context"
	"errors"

	v1 "server_go/api/v1"
	"server_go/internal/model"
	"server_go/internal/repository"

	"gorm.io/gorm"
)

type ArticleService interface {
	GetArticle(ctx context.Context, id int64) (*model.Article, error)
	CreateArticle(ctx context.Context, req v1.CreateArticleRequest) error
	DeleteArticle(ctx context.Context, articleId uint, userId uint, usertype int) error
	AdminReadArticle(ctx context.Context) ([]v1.ReadArticleReponse, error)
	ReadArticlebyUserId(ctx context.Context, userId uint) ([]v1.ReadArticleReponse, error)
}

func NewArticleService(
	service *Service,
	articleRepository repository.ArticleRepository,
	tagRepository repository.TagRepository,
	adiminRepository repository.AdiminRepository,

) ArticleService {
	return &articleService{
		Service:           service,
		articleRepository: articleRepository,
		tagRepository:     tagRepository,
		adiminRepository:  adiminRepository,
	}
}

type articleService struct {
	*Service
	articleRepository repository.ArticleRepository
	tagRepository     repository.TagRepository
	adiminRepository  repository.AdiminRepository
}

func (s *articleService) GetArticle(ctx context.Context, id int64) (*model.Article, error) {
	return nil, nil
}

func (s *articleService) CreateArticle(ctx context.Context, req v1.CreateArticleRequest) error {
	for _, tag := range req.Tags {
		_, err := s.tagRepository.GetTagByID(ctx, uint(tag))
		if err != nil {
			return v1.ErrTagNotFound
		}
	}
	_, err, articleID := s.articleRepository.CreateArticle(ctx, req)
	if err != nil {
		return err
	}
	for _, tag := range req.Tags {
		_, err = s.articleRepository.CreateArticleTag(ctx, tag, articleID)
		if err != nil {
			return err
		}
	}

	return err
}
func (s *articleService) DeleteArticle(ctx context.Context, articleId uint, userId uint, usertype int) error {
	err := s.tm.Transaction(ctx, func(ctx context.Context) error {
		if usertype != 1 {

			article, err := s.articleRepository.GetArticleByUserID(ctx, articleId, userId)
			if err != nil {
				return err
			}
			if article == nil {
				return v1.ErrArticleNotFound
			}
			err = s.articleRepository.DeleteArticle(ctx, articleId)
			if err != nil {
				return err
			}
			err = s.articleRepository.DeleteArticleTagByArticleId(ctx, articleId)
			if err != nil {
				return err
			}
		} else {
			err := s.articleRepository.DeleteArticle(ctx, articleId)
			if err != nil {
				return err
			}
			err = s.articleRepository.DeleteArticleTagByArticleId(ctx, articleId)
			if err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {

		return err
	}
	return nil
}

func (s *articleService) GetTagIdByArticleId(ctx context.Context, articleId uint) ([]uint, error) {

	tagId, err := s.articleRepository.GetTagIdByArticleId(ctx, articleId)
	if err != nil {
		return nil, err
	}
	return tagId, nil
}

func (s *articleService) AdminReadArticle(ctx context.Context) ([]v1.ReadArticleReponse, error) {
	articles, err := s.articleRepository.AdminReadArticle(ctx)
	if err != nil {
		return nil, err
	}
	var res []v1.ReadArticleReponse
	var user *model.Users
	for _, article := range *articles {
		tagId, err := s.GetTagIdByArticleId(ctx, article.ID)
		if err != nil {

			return nil, err
		}

		tagName := s.GetTagNameByID(ctx, tagId)
		user, err = s.adiminRepository.GetUserById(ctx, article.User_id)
		if err != nil {
			if !errors.Is(err, gorm.ErrRecordNotFound) {
				return nil, err
			}
			user = &model.Users{
				Name: "用户已注销",
			}
		}

		res = append(res, v1.ReadArticleReponse{
			ID:       article.ID,
			Title:    article.Title,
			Content:  article.Content,
			UserId:   article.User_id,
			UserName: user.Name,
			Tags:     tagName,
		})
	}
	return res, nil

}
func (s *articleService) GetTagNameByID(ctx context.Context, ids []uint) []string {
	var names []string
	for _, id := range ids {
		name, err := s.tagRepository.GetTagNameByID(ctx, id)
		if err != nil {
			return nil
		}
		names = append(names, name)

	}

	return names
}
func (s *articleService) ReadArticlebyUserId(ctx context.Context, userId uint) ([]v1.ReadArticleReponse, error) {
	article, err := s.articleRepository.QueryUserByUserId(ctx, userId)
	if err != nil {
		return nil, err
	}
	var res []v1.ReadArticleReponse
	for _, art := range article {
		tagId, err := s.GetTagIdByArticleId(ctx, art.ID)
		if err != nil {
			return nil, err
		}

		tagName := s.GetTagNameByID(ctx, tagId)

		res = append(res, v1.ReadArticleReponse{
			ID:      art.ID,
			Title:   art.Title,
			Content: art.Content,
			UserId:  art.User_id,
			Tags:    tagName,
		})
	}
	return res, nil
}
